﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml.Serialization;
using NUnit.Framework;
[Serializable]
[XmlRoot("Order")]
public class Order : IEquatable<Order>
{
    [XmlAttribute("ID")]
    public string OrderID { get; set; }
    [XmlElement("Client")]
    public Customer Customer { get; set; }
    [XmlArray("Items")]
    [XmlArrayItem("Product")]
    public List<OrderDetails> Details { get; set; } = new List<OrderDetails>();

    [XmlIgnore]
    public decimal Total => Details.Sum(d => d.UnitPrice * d.Quantity);

    public Order() { }

    public Order(string id) => OrderID = id;

    public bool Equals(Order other) => OrderID == other?.OrderID;
    public override bool Equals(object obj) => Equals(obj as Order);
    public override int GetHashCode() => OrderID.GetHashCode();

    public override string ToString() =>
    $"【订单号】{OrderID}\n【客户】{Customer}\n【总金额】{Total:C}\n{string.Join("\n", Details)}";
}

public class OrderDetails : IEquatable<OrderDetails>
{
    public string ProductName { get; }
    public decimal UnitPrice { get; }
    public int Quantity { get; }

    public OrderDetails(string name, decimal price, int qty)
    {
        ProductName = name;
        UnitPrice = price;
        Quantity = qty;
    }

    public bool Equals(OrderDetails other) => ProductName == other?.ProductName;
    public override bool Equals(object obj) => Equals(obj as OrderDetails);
    public override int GetHashCode() => ProductName.GetHashCode();

    public override string ToString() =>
    $"├ {ProductName} ×{Quantity}（单价：{UnitPrice:C}）";
}

public class Customer
{
    public string Name { get; set; }
    public string Phone { get; set; }
    public override string ToString() => $"{Name}（电话：{Phone}）";
}

public class OrderService
{
    public class SerializableOrder
    {
        [XmlAttribute("ID")]
        public string OrderID { get; set; }

        [XmlElement("Client")]
        public Customer Customer { get; set; }

        [XmlArray("Items")]
        public List<OrderDetailProxy> Details { get; set; } = new List<OrderDetailProxy>();
    }

    public class OrderDetailProxy
    {
        public string ProductName { get; set; }
        public decimal UnitPrice { get; set; }
        public int Quantity { get; set; }

        // 转换方法（禁用 new() 语法）
        public OrderDetails ToOriginal()
        {
            return new OrderDetails(
                this.ProductName,
                this.UnitPrice,
                this.Quantity
            );
        }

        public static OrderDetailProxy FromOriginal(OrderDetails detail)
        {
            return new OrderDetailProxy // 显式构造 
            {
                ProductName = detail.ProductName,
                UnitPrice = detail.UnitPrice,
                Quantity = detail.Quantity
            };
        }
    }

    private readonly List<Order> orders = new List<Order>();

    // 核心增删改查方法
    public void AddOrder(Order order)
    {
        if (orders.Any(o => o.Equals(order)))
            throw new InvalidOperationException($"订单 {order.OrderID} 已存在");
        orders.Add(order);
    }

    public void RemoveOrder(string orderId)
    {
        var order = GetOrder(orderId) ?? throw new KeyNotFoundException("订单不存在");
        orders.Remove(order);
    }

    public void UpdateOrder(string orderId, Customer newCustomer, List<OrderDetails> newDetails)
    {
        var order = GetOrder(orderId) ?? throw new KeyNotFoundException("订单不存在");
        order.Customer = newCustomer;
        order.Details.Clear();
        order.Details.AddRange(newDetails.Distinct());
    }

    // 多条件查询
    public IEnumerable<Order> Query(Func<Order, bool> predicate)
    {
        return orders.Where(predicate)
        .OrderBy(o => o.Total) // 始终按总金额升序排列
        .ThenBy(o => o.OrderID); // 金额相同按订单号排序
    }
    // 辅助方法
    private Order GetOrder(string id) => orders.FirstOrDefault(o => o.OrderID == id);


    public void Export(string path)
    {
        var proxyOrders = new List<SerializableOrder>(); // 显式类型声明 
        foreach (var o in orders)
        {
            proxyOrders.Add(new SerializableOrder // 传统初始化 
            {
                OrderID = o.OrderID,
                Customer = o.Customer,
                Details = o.Details.Select(d => OrderDetailProxy.FromOriginal(d)).ToList()
            });
        }

        var serializer = new XmlSerializer(typeof(List<SerializableOrder>));
        using (var fs = new FileStream(path, FileMode.Create))
        {
            serializer.Serialize(fs, proxyOrders);
        }
    }


    public void Import(string path)
    {
        if (!File.Exists(path)) throw new FileNotFoundException("XML文件不存在");

        var serializer = new XmlSerializer(typeof(List<SerializableOrder>));
        using (var fs = new FileStream(path, FileMode.Open))
        {
            var imported = (List<SerializableOrder>)serializer.Deserialize(fs);
            foreach (var proxy in imported)
            {
                var order = new Order(proxy.OrderID)
                {
                    Customer = proxy.Customer,
                    Details = new List<OrderDetails>() // 显式列表构造 
                };
                foreach (var d in proxy.Details)
                {
                    order.Details.Add(d.ToOriginal());
                }
                if (orders.Any(o => o.OrderID == order.OrderID))
                    throw new InvalidOperationException($"重复订单号: {order.OrderID}");
                orders.Add(order);
            }
        }
    }
}

[TestFixture]
public class OrderServiceTests
{
    private OrderService _service;
    private readonly string _testXmlPath = Path.Combine(TestContext.CurrentContext.TestDirectory, "test.xml");

    [SetUp]
    public void Setup()
    {
        _service = new OrderService();
        // 🔔初始化测试订单 
        var order = new Order("TEST_001")
        {
            Customer = new Customer { Name = "TestUser", Phone = "13800138000" },
            Details = { new OrderDetails("Monitor", 999.99m, 2) }
        };
        _service.AddOrder(order);
    }

    [Test]
    public void ExportImport_ShouldKeepDataConsistency()
    {
        // 导出测试 
        _service.Export(_testXmlPath);
        Assert.IsTrue(File.Exists(_testXmlPath));

        // 新建服务验证导入 
        var newService = new OrderService();
        newService.Import(_testXmlPath);
        var result = newService.Query(o => o.OrderID == "TEST_001").FirstOrDefault();

        Assert.Multiple(() => {
            Assert.NotNull(result, "订单丢失");
            Assert.AreEqual("TestUser", result.Customer.Name, "客户信息不一致");
            Assert.AreEqual(1999.98m, result.Total, "金额计算错误");
        });
    }


    [TearDown]
    public void Cleanup()
    {
        if (File.Exists(_testXmlPath))
            File.Delete(_testXmlPath);
    }
}

class Program
{
    static void Main()
    {
        var service = new OrderService();
        while (true)
        {
            Console.WriteLine("\n[1]添加 [2]删除 [3]修改 [4]查询 [5]退出");
            switch (Console.ReadLine()?.Trim())
            {
                case "1": AddOrderHandler(service); break;
                case "2": DeleteOrderHandler(service); break;
                case "3": UpdateOrderHandler(service); break;
                case "4": SearchOrderHandler(service); break;
                case "5": return;
            }
        }
    }

    static void DeleteOrderHandler(OrderService service)
    {
        try
        {
            Console.Write("输入要删除的订单号：");
            var orderId = Console.ReadLine();
            service.RemoveOrder(orderId);
            Console.WriteLine(" 删除成功");
        }
        catch (Exception ex)
        {
            ShowError(ex.Message);
        }
    }

    static void AddOrderHandler(OrderService service)
    {
        try
        {
            Console.Write("输入订单号：");
            var order = new Order(Console.ReadLine());

            Console.Write("客户姓名：");
            var customer = new Customer { Name = Console.ReadLine() };
            Console.Write("联系电话：");
            customer.Phone = Console.ReadLine();

            order.Customer = customer;
            AddDetails(order);
            service.AddOrder(order);
            Console.WriteLine(" 添加成功");
        }
        catch (Exception ex) { ShowError(ex.Message); }
    }

    static void AddDetails(Order order)
    {
        while (true)
        {
            Console.Write("商品名称（直接回车结束）：");
            var name = Console.ReadLine()?.Trim();
            if (string.IsNullOrWhiteSpace(name)) break;

            decimal price;
            while (true)
            {
                Console.Write("单价：");
                if (decimal.TryParse(Console.ReadLine(), out price) && price > 0)
                    break;
                ShowError("请输入正数（如：99.5）");
            }

            int qty;
            while (true)
            {
                Console.Write("数量：");
                if (int.TryParse(Console.ReadLine(), out qty) && qty > 0)
                    break;
                ShowError("请输入正整数（如：3）");
            }

            order.Details.Add(new OrderDetails(name, price, qty));
            Console.WriteLine($"已添加：{name} ×{qty}");
        }
    }

    static void UpdateOrderHandler(OrderService service)
    {
        try
        {
            Console.Write("输入要修改的订单号：");
            var orderId = Console.ReadLine();

            Console.Write("新客户姓名：");
            var customer = new Customer { Name = Console.ReadLine() };
            Console.Write("新联系电话：");
            customer.Phone = Console.ReadLine();

            var tempOrder = new Order("");
            AddDetails(tempOrder);
            service.UpdateOrder(orderId, customer, tempOrder.Details);
            Console.WriteLine("修改成功");
        }
        catch (Exception ex) { ShowError(ex.Message); }
    }
    static void SearchOrderHandler(OrderService service)
    {
        Console.WriteLine("【查询方式】1.按商品 2.按客户 3.按金额范围 4.按订单号");
        Console.Write("请选择：");
        switch (Console.ReadLine())
        {
            case "1":
                Console.Write("输入商品名称：");
                foreach (var o in service.Query(o => o.Details.Any(d => d.ProductName.Contains(Console.ReadLine()))))
                    Console.WriteLine(o + "\n------------");
                break;

            case "2":
                Console.Write("输入客户名称：");
                foreach (var o in service.Query(o => o.Customer.Name.Contains(Console.ReadLine())))
                    Console.WriteLine(o + "\n------------");
                break;

            case "3":
                Console.Write("最低金额：");
                var min = decimal.Parse(Console.ReadLine());
                Console.Write("最高金额：");
                var max = decimal.Parse(Console.ReadLine());
                foreach (var o in service.Query(o => o.Total >= min && o.Total <= max))
                    Console.WriteLine(o + "\n------------");
                break;

            case "4":
                Console.Write("输入订单号：");
                var order = service.Query(o => o.OrderID == Console.ReadLine()).FirstOrDefault();
                Console.WriteLine(order != null ? order.ToString() : "⚠ 未找到该订单");
                break;

            default:
                ShowError("无效的查询选项");
                break;
        }
    }
    static void ShowError(string msg)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine($"！ {msg}");
        Console.ResetColor();
    }
}